/**$Licence:
 *   Use this however/wherever you like, just don't blame me if it breaks anything.
 *   Copyright (C) 2008 - 2012 xingsheng.zhu@gmail.com All rights reserved.
 */
package com.blazemina.command;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import com.blazemina.config.ActionConfig;
import com.blazemina.config.BlazeminaConfig;
import com.blazemina.config.BlazeminaConfigManager;
import com.blazemina.mina.Request;
import com.blazemina.mina.Response;

/**
 * command的复用，根据blazemina-config.xml的中method配置，执行不同的method，达到对command的共用
 * @author JackChu
 * @version 1.0.0 2012-1-11 下午4:07:54
 */
public class DispatchCommand extends GecericCommand {

	protected BlazeminaConfig blazeminaConfig = BlazeminaConfigManager
			.getManager().getBlazeminaConfig();

	protected Class[] types = { Request.class, Response.class };

	/**
	 * The Class instance of this <code>CommandDispatcher</code> class.
	 */
	protected Class clazz = this.getClass();

	@Override
	public void execute(Request request, Response response) {
		Method method = getMethod(request);
		try {
			method.invoke(this, new Object[] { request, response });
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private Method getMethod(Request request) {
		Method method = getMethodFromConfig(request);
		if (method == null) {
			method = getMethodFromReflect(request);
		}
		return method;
	}

	/**
	 * 从{@link ActionConfig}取得需要执行的Method
	 * 
	 * @param request
	 * @return
	 */
	private Method getMethodFromConfig(Request request) {
		String name = request.getMessage().getCommand();
		ActionConfig commandConfig = blazeminaConfig.getProtocols().findCommandConfig(name);
		Method method = commandConfig.getMethod();
		return method;
	}

	private synchronized Method getMethodFromReflect(Request request) {
		Method method = getMethodFromConfig(request);
		if (method == null) {
			String name = request.getMessage().getCommand();
			ActionConfig commandConfig = blazeminaConfig.getProtocols().findCommandConfig(name);
			String methodName = commandConfig.getMethodName();
			try {
				method = clazz.getMethod(methodName, types);
			} catch (SecurityException e) {
				e.printStackTrace();
			} catch (NoSuchMethodException e) {
				e.printStackTrace();
			}
			commandConfig.setMethod(method);
		}
		return method;
	}

	protected void dispatchMethod() {

	}

}
